package br.com.delogic.simuladorbancario.main.business;

import br.com.delogic.simuladorbancario.main.exception.ValidacaoRuntimeException;
import br.com.delogic.simuladorbancario.main.model.Cliente;
import br.com.delogic.simuladorbancario.main.model.ClienteFisico;
import br.com.delogic.simuladorbancario.main.model.SituacaoCliente;
import br.com.delogic.simuladorbancario.main.model.Sucesso;
import br.com.delogic.simuladorbancario.main.model.UnidadeFederativa;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *
 * @author NB1
 */
public class ClienteBusiness {

    private final Map<Integer, Cliente> clientes = new HashMap<Integer, Cliente>();
    private static ClienteBusiness clienteBusiness;

    private ClienteBusiness() {
        Cliente newCliente;
        for (int i = 0; i < 5; i++) {
            newCliente = new ClienteFisico();
            newCliente.setCodigo(i + 1);
            newCliente.setNome("Teste");
            newCliente.setSobrenome(Integer.toString(i));
            newCliente.setLogradouro("Lugar " + i);
            newCliente.setCidade("Cidade " + i);
            newCliente.setTelefone("12345" + i);
            newCliente.setEmail(i + "@" + i + "." + i);
            newCliente.setUf(UnidadeFederativa.values()[(int) Math.floor(Math.random() * 4)]);
            cadastrarCliente(newCliente);
        }
    }

    public static ClienteBusiness getInstance() {
        if (clienteBusiness == null) {
            clienteBusiness = new ClienteBusiness();
        }
        return clienteBusiness;
    }

    public Sucesso cadastrarCliente(Cliente cliente) {
        List<String> campos = new ArrayList<String>();

        if (cliente.getNome() == null || cliente.getNome().isEmpty()) {
            campos.add("nome");
        }
        if (cliente.getSobrenome() == null || cliente.getSobrenome().isEmpty()) {
            campos.add("sobrenome");
        }
        if (!campos.isEmpty()) {
            throw new ValidacaoRuntimeException("Os campos marcados não podem ser vazios", campos);
        }
        
        cliente.setSituacao(SituacaoCliente.ATIVO);
        cliente.setCodigo(clientes.size() + 1);
        clientes.put(cliente.getCodigo(), cliente);
        return new Sucesso(
                String.format("Cliente %s cadastrado com sucesso!",
                        cliente.getNome()));
    }
    
    public void lancarException (String mensagem, List<String> campos) {
        throw new ValidacaoRuntimeException(mensagem, campos);
    }

    public Cliente consultarClientePorCodigo(Integer codigo) {
        return clientes.get(codigo);
    }

    public Sucesso alterarCliente(Cliente cliente) {
        if (cliente == null) {
            return null;
        }
        cadastrarCliente(cliente);
        return new Sucesso(
                String.format("Cliente %s alterado com sucesso!",
                        cliente.getNome()));
    }

    public Sucesso bloquearCliente(Integer codCliente) {
        Cliente cliente = clientes.get(codCliente);
        if (cliente == null) {
            return null;
        }
        cliente.setSituacao(SituacaoCliente.BLOQUEADO);
        return new Sucesso(
                String.format("Cliente %s bloqueado com sucesso!",
                        cliente.getNome()));
    }

    public Sucesso reativarCliente(Integer codCliente) {
        Cliente cliente = clientes.get(codCliente);
        if (cliente == null) {
            return null;
        }
        cliente.setSituacao(SituacaoCliente.ATIVO);
        return new Sucesso(
                String.format("Cliente %s reativado com sucesso!",
                        cliente.getNome()));
    }

    public Sucesso cancelarCliente(Integer codCliente) {
        Cliente cliente = clientes.get(codCliente);
        cliente.setSituacao(SituacaoCliente.CANCELADO);
        return new Sucesso(
                String.format("Cliente %s cancelado com sucesso!",
                        cliente.getNome()));
    }

    public List<Cliente> consultarPorNome(String nome) {
        List<Cliente> clientesEncontrados = new ArrayList<Cliente>();
        for (Cliente cliente : clientes.values()) {
            if (cliente.getNome().toLowerCase().contains(nome.toLowerCase())) {
                clientesEncontrados.add(cliente);
            }
        }
        return clientesEncontrados;
    }

    public Cliente consultarPorCPF(String cpf) {
        for (Cliente cliente : clientes.values()) {
            if (cliente instanceof ClienteFisico
                    && ((ClienteFisico) cliente).getCadastro().equals(cpf)) {
                return cliente;
            }
        }
        return null;
    }

    public Cliente consultarPorCNPJ(String cnpj) {
        for (Cliente cliente : clientes.values()) {
            if (cliente instanceof ClienteFisico
                    && ((ClienteFisico) cliente).getCadastro().equals(cnpj)) {
                return cliente;
            }
        }
        return null;
    }
    
    public List<Cliente> listar() {
        return new ArrayList<Cliente>(clientes.values());
    }
}
